import { ForbiddenException, Injectable } from "@nestjs/common";
import { UserService } from "./user.service";
import { TokenService } from "./token.service";
import { UserRepository } from "../repository";
import { QueryHook } from "src/config/types";
import { UserEntity } from "../entity/user.entity";
import { SelectQueryBuilder } from "typeorm";
import { decrypt, defaultUserConfig } from '../helper';
import dayjs from "dayjs";
import { FastifyRequest as Request } from 'fastify';
import { ExtractJwt } from 'passport-jwt';
import { RegisterDto, UpdatePasswordDto } from "../dto/user.dto";
import { JwtModule } from "@nestjs/jwt";
@Injectable()
export class AuthService {
    constructor(
        private readonly userService: UserService,
        private readonly tokenService: TokenService,
        protected readonly userRepository: UserRepository,
    ) {}

    //用户验证登录
    async validatorUser(credential:string,password:string){
        let user=await this.userService.findOneByCredential(credential,async (qb:SelectQueryBuilder<UserEntity>)=>{
            return qb.addSelect('user.password')
        })

        //判断用户是否存在密码是否正确
        if(user&&decrypt(password,user.password)){
            return user
        }
        return false

    }
    //登录 用户 并生成 新的token 和 refreshToken
    // 

    async login (user:UserEntity){
        const now=  dayjs(new Date())
        const {accessToken}=await this.tokenService.generateAccessToken(user,now)
        return accessToken.value
    }

    //注销登录
    async logout(req:Request){
        // ExtractJwt.fromAuthHeaderAsBearerToken()(req as any); 从前端的 heard 上直接 获取token
        const accessToken=ExtractJwt.fromAuthHeaderAsBearerToken()(req as any)
            if(accessToken){
                await this.tokenService.removeAccessToken(accessToken)
            }
            return {
                msg: 'logout_success',
            };
    }
    async createToken(id: string){
        const now=dayjs(new Date())
        let user:UserEntity
        try {
            user= await this.userRepository.findOne({where:{id}})
        } catch (error) {
            throw new ForbiddenException();
        }

        //获取token
        const {accessToken}=await this.tokenService.generateAccessToken(user,now)
        return accessToken.value
    }

    //使用用户名和密码注册用户
    async register(data:RegisterDto){
        const { username, nickname, password } = data;
        const user = await this.userService.create({
            username,
            nickname,
            password,
            actived: true,
        } as any);

      //  return this.userService.findOneByCondition({ id: user.id });
    }
    async updatePassword(user: UserEntity, { password, oldPassword }: UpdatePasswordDto){
        const item= await this.userRepository.findOneOrFail({
            select:['password'],
            where:{id:user.id}
        })

        if(decrypt(item.password,password)){
            throw new ForbiddenException('old password not matched');
        }
        item.password=password
        await this.userRepository.save(item)
        //return this.userService.findOneByCondition()
    }
   
    static jwtModuleFactory() {
        return JwtModule.registerAsync({
            useFactory:async ()=>{
                const config=defaultUserConfig()
                return{
                    secret:config.jwt.secret,
                    ignoreExpiration:true,
                    signOptions: { expiresIn: `${config.jwt.token_expired}s` },
                }
            }
        })
    }
}